<?php
/** Clasa principala pentru controlul executiei in AMFramework; 
 * se instantiaza in index.php; initializarea (cu `init`) obiectului instantiaza
 * si initializeaza principalele biblioteci si configuratia frameworkului.
 * Chemarea metodei `run` va instantia punctul de intrare al uneia dintre 
 * aplicatiile finale.
 * 
 * @package	AMFramework
 * @subpackage Core
 * @author 	Marcu Alexandru
 * @version v1.0 $Build: 305b
 */
defined('_INDEX') or die('Restricted');

class Amfw_Application extends Amfw_Object {

	protected $_config;		// Obiect de tip Amfw_Config
	protected $_doc;		// Obiect de tip Amfw_Document
	
	private static $application;	// Array de `oglindire` al aplicatiei finale ce
									// este rulata; contine configuratia si detalii 
									// pentru initializare (template,db,localizare,etc)

	public function __construct() 
	{
		// Configuratia generala pentru framework
		$this->_config = new Amfw_Config();
		$this->_config->init();
		
		// Inregistrare autoloader
		spl_autoload_register('fwAutoload');
	}

	// Metoda ce intoarce proprietatea $application; metoda se cheama static;
	public static function _() { return self::$application; }

	// Initializeaza elementele principale ale platformei
	public function init() 
	{
		// Initializarea trebuie sa pastreze ordinea specificata
		$this->__initMethods('Core','Session','Document');
		
		// Zona in care se pot face teste
	}

	// Metoda cauta aplicatia finala trecand prin urmatorii pasi:
	// (1) Decide daca ruta spre aplicatie este definita explicit in URL 
	// sau daca trebuie utilizat mecanismul de rutare; (2) Indiferent de caz,
	// se preia informatia despre aplicatia finala ce va fi utilizata  
	protected function _initCore() 
	{
		Amfw_Router::fetchRoutingCnf();
		(Amfw_Router::enabled()) ? Amfw_Router::fetchUriCommand() : null;

		// Preluarea datelor despre aplicatia finala ce va fi folosita
		$this->fetchApplication();
		
		// Daca dispozitivul de rutare este activat se va crea cererea
		// interpretandu-se tokenurile dupa reguli definite de catre programator
		(Amfw_Router::enabled()) ? Amfw_Router::fetchTokens() : null;
		(Amfw_Router::enabled()) ? Amfw_Router::createRequest() : null;
	}
	

	 // Creeaza documentul aplicatiei finale;
	protected function _initDocument() {
		$this->_doc = new Amfw_Document();
		$this->_doc->init();
	}


	// Implementeaza algoritmul prin care se preiau informatiile
	// despre aplicatia finala;
	private function fetchApplication() {
		
		$apps = $this->getConfig('applications');
		$default = array_shift($apps);
		
		// Incepem prin a cauta aplicatia in cerere
		$req = Amfw_Request::getv('application');
		if(isset($req)):
			Amfw_Debug::toJournal('Cautam aplicatia finala in cerere (Routing: Off)',110);
			foreach($apps as $app) {
				if(strtolower($app->name) == strtolower($req)){
					self::$application = $app;
					return;
				}//~!if
			}//~!foreach
		endif;
		// Acum cautam aplicatia in ruta (daca rutarea este activata)
		if(Amfw_Router::enabled()):
			Amfw_Debug::toJournal('Cautam aplicatia finala in cerere (Routing: On)',110,1);
			$command = Amfw_Router::command();
			$command = array_shift($command); // Daca este in ruta, trebuie sa fie mereu primul token
			foreach($apps as $app) {
				if(strtolower($app->name) == strtolower($command)) {
			 		self::$application = $app;
			 		return;
			 	}//~!if
			 }//~!foreach
		endif;

		Amfw_Debug::toJournal('Se utilizeaza aplicatia implicita',110);
		self::$application = $default;
		return;
	}
	
	//  Initializeaza sesiunea;
	protected function _initSession() {
		$sess =& Amfw_Factory::getSession();
	}
	
	// Metoda instantiaza punctul de intrare al aplicatiei finale;
	// daca nu este prezenta nici o aplicatie scriptul se incheie.
	public function run() 
	{
		$c_load	= $this->_config->getFwConstants('Default_Application_EntryPoint_Name'); 
		
		// Cand nu este gasita nici o aplicatie valida, scriptul este intrerupt
		$app 	= self::_() or die('No valid application found in '.APP_PATH.'.');
		$loader	= $app->prefix . '_' . $c_load;
		
		new $loader();
	}

	// Getter pentru configuratie; parametri $type si $cname sunt 
	// scurtaturi pentru o anumita sectiune respectiv pentru obtinerea
	// unei anumite constante de framework (cand $type == 'constants')
	public function getConfig( $type = null, $cname = null )
	{
		if(!isset( $type )): return $this->_config;
		else:
			switch( $type ) 
			{
				// Libraries --------------------------------------------------
				case 'libs'			:
				case 'libraries'	:
					return $this->_config->getLibraries();

				// Applications -----------------------------------------------
				case 'apps'			:
				case 'applications' :
					return $this->_config->getApplications();

				// Constants --------------------------------------------------
				case 'const'	:
				case 'constants':
					if(isset( $cname )) 
						return $this->_config->getFwConstants($cname);
					else return $this->_config->getFwConstants();

				// Routing --------------------------------------------------
				case 'routing'	:
					return $this->_config->getRouting();

				// Error ------------------------------------------------------
				default	:
					$error 	=  "<u>framework->getConfig()</u> can't use the shortcut 
								<b>$type</b>: no config of this type.<br/>";
					Amfw_Debug::toJournal($error, D_NOTE);
					return $this->_config;
				// ------------------------------------------------------------
			}
		endif;
	}

	// Getter pentru documentul atasat obiectului
	public function getDocument() {
		return $this->_doc;
	}
}